<?php
namespace app\common\service;

use app\common\service\book\BookService;
use app\common\service\weixin\TemplateService;
use app\models\book\Book;
use app\models\pay\PayOrder;
use app\models\pay\PayOrderCallbackData;
use app\models\pay\PayOrderItem;
use Behat\Gherkin\Exception\Exception;

class PayOrderService extends BaseService
{
    /**
     * 下单方法
     * $items = [
     *      [ "target_id","target_type","price",quantity ]
     * ]
     */
    public static function createPayOrder($member_id, $items = [], $params = [])
    {
        $total_price = 0;
        $continue_cnt = 0;
        foreach ($items as $_item) {
            if ($_item['price'] < 0) {
                $continue_cnt++;
                continue;
            }
            $total_price += $_item['price'];
        }

        if ($continue_cnt >= count($items)) {
            return self::_err("商品items为空~~");
        }

        $discount = isset($params['discount']) ? $params['discount'] : 0;
        $total_price = sprintf("%.2f", $total_price);  //总金额
        $discount = sprintf("%.2f", $discount);        //优惠金额
        $pay_price = $total_price - $discount;
        $pay_price = sprintf("%.2f", $pay_price);      //付款金额
        $date_now = date("Y-m-d H:i:s");

        //事物
        $connection = PayOrder::getDb();
        $transaction = $connection->beginTransaction();

        try {
            //并发控制  select for update
            $tmp_book_table_name = Book::tableName();
            $tmp_book_ids = array_column($items, "target_id");
            $tmp_sql = "select id,stock from {$tmp_book_table_name} where id in(" . implode(",", $tmp_book_ids) . ") FOR UPDATE";
            $tmp_book_list = $connection->createCommand($tmp_sql)->queryAll();
            $tmp_book_unit_mapping = [];
            foreach ($tmp_book_list as $_book_info) {
                $tmp_book_unit_mapping[$_book_info['id']] = $_book_info['stock'];
            }

            $model_pay_order = new PayOrder();
            $model_pay_order->order_sn = self::generate_order_sn();
            $model_pay_order->member_id = $member_id;
            $model_pay_order->pay_type = isset($params['pay_type']) ? $params['pay_type'] : 0;
            $model_pay_order->pay_source = isset($params['pay_source']) ? $params['pay_source'] : 0;
            $model_pay_order->target_type = isset($params['target_type']) ? $params['target_type'] : 0;
            $model_pay_order->total_price = $total_price;
            $model_pay_order->discount = $discount;
            $model_pay_order->pay_price = $pay_price;
            $model_pay_order->note = isset($params['note']) ? $params['note'] : '';
            $model_pay_order->status = isset($params['status']) ? $params['status'] : '';
            $model_pay_order->express_status = isset($params['express_status']) ? $params['express_status'] : -8;
            $model_pay_order->express_address_id = isset($params['express_address_id']) ? $params['express_address_id'] : 0;
            $model_pay_order->pay_time = ConstantMapService::$default_time_stamps;
            $model_pay_order->updated_time = $date_now;
            $model_pay_order->created_time = $date_now;

            if (!$model_pay_order->save(0)) {
                throw new \Exception("创建订单失败~~");
            }

            foreach ($items as $_item) {
                $tmp_left_stock = $tmp_book_unit_mapping[$_item['target_id']];
                if ($tmp_left_stock < $_item['quantity']) {
                    throw new \Exception("购买书籍库存不够，目前剩余库存：{$tmp_left_stock},您购买：{$_item['quantity']}~~");
                }

                if (!Book::updateAll(['stock' => $tmp_left_stock - $_item['quantity']], ['id' => $_item['target_id']])) {
                    throw new \Exception("下单失败，请重新下单~~");
                }

                $model_item = new PayOrderItem();
                $model_item->pay_order_id = $model_pay_order->id;
                $model_item->member_id = $member_id;
                $model_item->quantity = $_item['quantity'];
                $model_item->price = $_item['price'];
                $model_item->target_id = $_item['target_id'];
                $model_item->target_type = $_item['target_type'];
                $model_item->status = isset($_item['status']) ? $_item['status'] : 1;
                $model_item->note = isset($_item['note']) ? $_item['note'] : '';
                $model_item->updated_time = $date_now;
                $model_item->created_time = $date_now;
                if (!$model_item->save(0)) {
                    throw new \Exception("创建订单失败~~");
                }

                BookService::setStockChangeLog($_item['target_id'], -$_item['quantity'], '在线购买');

            }
            $transaction->commit();

            return [
                'id' => $model_pay_order->id,
                'order_sn' => $model_pay_order->order_sn,
                'pay_money' => $model_pay_order->pay_price
            ];


        } catch (\Exception $e) {
            $transaction->rollBack();
            return self::_err($e->getMessage());
        }

    }

    public static function orderSuccess( $pay_order_id ,$params = []){
        $date_now = date("Y-m-d H:i:s");
        $connection = PayOrder::getDb();
        $transaction = $connection->beginTransaction();
        try{
            $pay_order_info = PayOrder::findOne([ 'id' => $pay_order_id ]);
            if( !$pay_order_info || !in_array( $pay_order_info['status'],[-8,-7] ) ){
                throw new \Exception("订单不存在或状态不对~~");
            }
            $pay_order_info->pay_sn = isset( $params['pay_sn'] )?$params['pay_sn']:'';
            $pay_order_info->status = 1;
            $pay_order_info->express_status = 1;
            $pay_order_info->pay_time = $date_now;
            $pay_order_info->updated_time = $date_now;
            $pay_order_info->update(0);

            $items = PayOrderItem::findAll( ['pay_order_id' => $pay_order_id] );
            foreach( $items as $_item ){
                switch ( $_item['target_type'] ){
                    case 1:
                        //图书基本处理
                        BookService::confirmOrderItem( $_item['id'] );
                        break;
                }
            }

            $transaction->commit();


        }catch ( \Exception $e ){
            $transaction->rollBack();
            return self::_err($e->getMessage());
        }

//        TemplateService::PayNotice( $pay_order_id );
            QueueListService::addQueue('pay',[
                'member_id' => $pay_order_info['member_id'],
                'pay_order_id' => $pay_order_id
            ]);


    }

    public static function generate_order_sn(){
        do{
            $sn = md5( microtime( 1 ).rand( 0,999999 )."#@%egg#$" );
        }while( PayOrder::findOne( ['order_sn' => $sn] ) );
        return $sn;
    }

    public static function setPayOrderCallbackData( $pay_order_id,$type,$callback = '' ){
        if( !$pay_order_id ){
            return self::_err("pay_order_id不能为空~~");
        }
        if( !in_array( $type,['pay','refund'] ) ){
            return self::_err("参数类型错误~~");
        }
        $pay_order = PayOrder::findOne([ 'id' =>$pay_order_id ]);
        if( !$pay_order ){
            return self::_err("找不到订单号为{$pay_order_id}的订单~~");
        }

        $callback_data = PayOrderCallbackData::findOne(['pay_order_id' => $pay_order_id]);
        if( !$callback_data ){
            $callback_data = new PayOrderCallbackData();
            $callback_data->pay_order_id = $pay_order_id;
            $callback_data->created_time = date('Y-m-d H:i:s');
        }

        if( $type == 'refund' ){
            $callback_data->refund_data = $callback;
            $callback_data->pay_data = '';
        }else{
            $callback_data->refund_data = '';
            $callback_data->pay_data = $callback;
        }
        $callback_data->updated_time = date('Y-m-d H:i:s');
        $callback_data->save(0);
        return true;
    }

    public static function  closeOrder( $pay_order_id = 0 ){
        $date_now = date("Y-m-d H:i:s");
        $pay_order_info = PayOrder::find()->where(['id' => $pay_order_id,'status' => -8])->one();
        if( !$pay_order_info ){
            return self::_err("指定订单不存在~~");
        }

        $pay_order_items = PayOrderItem::findAll(['pay_order_id' => $pay_order_id]);


        if( $pay_order_items ){
            foreach( $pay_order_items as $_order_item_info ){
                switch( $_order_item_info['target_type'] ){
                    case 1:
                        $tmp_book_info = Book::find()->where(['id' =>$_order_item_info['target_id']])->one();
                        if($tmp_book_info){
                            $tmp_book_info->stock += $_order_item_info['quantity'];
                            $tmp_book_info->updated_time = $date_now;
                            $tmp_book_info->update( 0 );
                            BookService::setStockChangeLog( $_order_item_info['target_id'],$_order_item_info['quantity'],"订单过期释放库存" );
                        }
                        break;
                }
            }
        }

        $pay_order_info->status = 0;
        $pay_order_info->updated_time = $date_now;
        return $pay_order_info->update(0);
    }
}
